import Control.Arrow (first, second)
import Data.Char (digitToInt)
import Numeric (readHex)
import Utils (tok)

data Direction = R | D | L | U deriving (Show, Eq, Enum)
type Count     = Int 
type Color     = String
type Entry     = (Direction, Count)
type Coord     = (Int, Int)

path :: Coord -> [Entry] -> [Coord]
path pos es = 
    scanl step pos es
    where
        step :: Coord -> Entry -> Coord
        step p (D, i) = first (+i) p
        step p (R, i) = second (+i) p
        step p (L, i) = second (-i+) p
        step p (U, i) = first (-i+) p

area :: [Coord] -> Int
area cs = abs . (`div` 2) .sumOfProducts $ cs
    where
        sumOfProducts (_:[]) = 0
        sumOfProducts ((y1, x1) : c2@(y2, x2) : cs) = p + sumOfProducts (c2:cs)
        where
            p = (y1 + y2) * (x1 - x2)

solve :: [Entry] -> Int
solve steps = 
    a + (b `div` 2) + 1
    where
        boundary = path (0, 0) steps
        a        = area $ boundary
        b        = sum . map snd $ steps

parseLine :: String -> Entry
parseLine l = 
    (dir, cnt)
    where
        tokens = tok " " 1
        dir    = case (tokens !! 0) of {
            "U" -> U;
            "D" -> D;
            "L" -> L;
            "R" -> R
        }
        cnt    = read $ tokens !! 1

parseLine2 :: String -> Entry
parseLine2 l = 
    (dir, cnt)
    where
        hex = init . drop 2 . last . tok " " $ l
        dir = toEnum . digitToInt . last $ hex
        cnt = fst . head . readHex . init $ hex
        
main = do
  
    filecontents <- readFile "input.txt"

    -- Part 1
    print $ solve . map parseLine . lines $ filecontents

    -- Part 2
    print $ solve . map parseLine2 . lines $ filecontents

    print $ "---------- Done. ----------"